import os
from utils.common import load_logging_config, load_from_json,return_ins,dynamic_import,parseParams,load_weights_keras,load_weights_pytorch,load_model_from_framework_save_keras,load_model_from_framework_save_pytorch
import json
import types
import shutil
import keras
import numpy as np
import tensorflow as tf
import torch.nn as nn
import importlib

# if tf.__version__.startswith('2.14'):
#     keras_model_type=(keras.src.engine.functional.Functional,tf.keras.Model,tf.keras.models.Model)
# elif tf.__version__.startswith('2.11'):
#     keras_model_type=(keras.engine.functional.Functional,keras.engine.training.Model,tf.keras.Model,tf.keras.models.Model)
# elif tf.__version__.startswith('2.16'):
#     keras_model_type=(keras.src.models.functional.Functional,tf.keras.Model,tf.keras.models.Model)
# else:
#     keras_model_type=(keras.engine.functional.Functional,keras.engine.training.Model,tf.keras.Model,tf.keras.models.Model)

# pytorch_model_type=(nn.Module,)

keras_model_type=[]
pytorch_model_type=[]
with open('system_config.json','r',encoding='utf8') as f:
    sc=json.load(f)
for kmt in sc['keras_model_type_'+sc['tf_version']]:
    modulename,classname=kmt.rsplit('.',1)
    keras_model_type.append(getattr(importlib.import_module(modulename),classname))
for pmt in sc['pytorch_model_type']:
    modulename,classname=pmt.rsplit('.',1)
    pytorch_model_type.append(getattr(importlib.import_module(modulename),classname))
keras_model_type=tuple(keras_model_type)
pytorch_model_type=tuple(pytorch_model_type)

def instance_variable_name_of_class(classname):
    if ord(classname[0])>=65 and ord(classname[0])<91:
        return classname[0].upper()+classname[1:]
    else:
        return '_'+classname

def build_model(model,dataset,preprocessor,filename,type):
    '''
    生成训练模型的代码

    Args:
        model: 模型字典
        dataset: 数据集字典
        preprocessor: 预处理器字典
        filename: 生成的python文件路径
        type: 测试类型
    '''
    with open(filename, 'w', encoding='utf8') as f:
        contents='''
import sys
import os

from procedures import train_procedure

sys.path.append(%s)

from %s import %s

model_init_d=%s
%s=%s(**model_init_d)
train_procedure(%s,%s)
'''%(os.path.basename(model['file'])[:-3],model['class'],os.path.dirname(model['file']),model['parameters'],instance_variable_name_of_class(model['class']),model['class'],instance_variable_name_of_class(model['class']),dataset['path'])
        f.write(contents)

def get_flops(model):
    if isinstance(model,keras_model_type):
        run_meta=tf.compat.v1.RunMetadata()
        opts=tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()
        from tensorflow.python.framework.convert_to_constants import (convert_variables_to_constants_v2_as_graph)
        inputs=[tf.TensorSpec([1]+list(inp.shape[1:]),inp.dtype) for inp in model.inputs]
        real_model=tf.function(model).get_concrete_function(inputs)
        frozen_func,_=convert_variables_to_constants_v2_as_graph(real_model)
        flops=tf.compat.v1.profiler.profile(graph=frozen_func.graph,run_meta=run_meta,cmd="scope",options=opts)
        return flops.total_float_ops

def get_network_json(model):
    network_json={}
    if isinstance(model,keras_model_type):
        inputLayers=[]
        outputLayers=[]
        structure={}
        for layer in model.layers:
            cur_ins=[]
            cur_outs=[]
            if not isinstance(layer.input,list):
                cur_ins=layer.input.name.split('/')[0]
            else:
                for li in layer.input:
                    cur_ins.append(li.name.split('/')[0])
            if not isinstance(layer.output,list):
                cur_outs=layer.output.name.split('/')[0]
            else:
                for lo in layer.output:
                    cur_outs.append(lo.name.split('/')[0])
            if not isinstance(cur_ins,list):
                structure[cur_ins]=cur_outs
            else:
                for ci in cur_ins:
                    structure[ci]=cur_outs

        for i in range(len(model.inputs)):
            if model.inputs[i].dtype==tf.int32:
                dtyp='int32'
            elif model.inputs[i].dtype==tf.float32:
                dtyp='float32'
            elif model.inputs[i].dtype==tf.float64:
                dtyp='float64'
            elif model.inputs[i].dtype==tf.int8:
                dtyp='int8'
            else:
                dtyp='float32'
            inputLayers.append({model.inputs[i].name:[list(model.inputs[i].shape),dtyp]})
        for i in range(len(model.outputs)):
            if model.outputs[i].dtype==tf.int32:
                dtyp='int32'
            elif model.outputs[i].dtype==tf.float32:
                dtyp='float32'
            elif model.outputs[i].dtype==tf.float64:
                dtyp='float64'
            elif model.outputs[i].dtype==tf.int8:
                dtyp='int8'
            else:
                dtyp='float32'
            outputLayers.append({model.outputs[i].name:[list(model.outputs[i].shape),dtyp]})

        tvn=ntvn=0
        for tv in model.trainable_variables:
            tvn+=np.prod(tv.shape)
        for ntv in model.non_trainable_variables:
            ntvn+=np.prod(ntv.shape)

        network_json['structure']=json.dumps(structure)
        network_json['inputs']=','.join([json.dumps(i) for i in inputLayers])
        network_json['outputs']=','.join([json.dumps(o) for o in outputLayers])
        network_json['param_statistics']={'total':int(tvn+ntvn),'trainable':int(tvn),'non':int(ntvn)}
        network_json['FLOPs']=get_flops(model)
    # 参考链接：
    # https://zhuanlan.zhihu.com/p/657887156
    # https://blog.csdn.net/qq_35407318/article/details/109359006
    # https://www.cnblogs.com/emanlee/p/17560584.html
    # https://blog.csdn.net/tywwwww/article/details/126782766
    # https://blog.csdn.net/lishuiwang/article/details/104510200
    elif isinstance(model,pytorch_model_type):
        structure=''
        for i in model.named_children():
            structure+=str(i)

        tvn=ntvn=0
        for p in model.parameters():
            if p.requires_grad:
                tvn+=p.nelement()
            else:
                ntvn+=p.nelement()
        # 需要知道网络的输入变量的形状，不需要点明批量大小（默认为1？）
        # from ptflops import get_model_complexity_info
        # macs,params=get_model_complexity_info(model,(1,128,2000))
        # print(macs,params)

        network_json['structure']=structure
        network_json['inputs']=''
        network_json['outputs']=''
        network_json['param_statistics']={'total':int(tvn+ntvn),'trainable':int(tvn),'non':int(ntvn)}
        network_json['FLOPs']=-1
    return network_json

def isLoadableModelSource(model):
    if isinstance(model,object):
        return True
    else:
        return False

def get_model_ins_from_json(acoustic_model_json,situation):
    if situation=='train' or situation=='infer':
        if acoustic_model_json['weights_file']=='':
            if acoustic_model_json['filetype']=='source':
                modulename=acoustic_model_json['modulename']
                classname=acoustic_model_json['classname']
                attribute=acoustic_model_json['attribute']
                parameters=acoustic_model_json['parameters']

                if acoustic_model_json['infer_classname']!='':
                    if acoustic_model_json['infer_classname']==acoustic_model_json['classname']:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        ins=obj(*t,**d)
                        res=list()
                        for a in (attribute,acoustic_model_json['infer_attribute']):
                            if a=='':
                                res.append(ins)
                            else:
                                func_params=a.split('(',1)
                                ins1=getattr(ins,func_params[0])
                                if len(func_params)>1:
                                    t,d=parseParams(func_params[1][:-1])
                                    res.append(ins1(*t,**d))
                                else:
                                    res.append(ins1)
                        return tuple(res)
                    else:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        infer_obj=dynamic_import(f'{modulename}:{acoustic_model_json["infer_classname"]}')
                        infer_t,infer_d=parseParams(acoustic_model_json['infer_parameters'])
                        return obj(*t,**d),infer_obj(*infer_t,**infer_d)
                elif len(acoustic_model_json['infer_input_layer_names'])!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,tf.keras.models.Model):
                        model_inputs=[]
                        model_outputs=[]
                        if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in acoustic_model_json['infer_input_layer_names']:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in acoustic_model_json['infer_output_layer_name']:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                    return model,infer_model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    return model,model
            
            elif acoustic_model_json['filetype']=='framework_save':
                if acoustic_model_json['framework']=='tf.keras':
                    model=load_model_from_framework_save_keras(acoustic_model_json['file'],acoustic_model_json['file_ext']) # acoustic_model_json['file_ext']必须=='saved_model'

                    if len(acoustic_model_json['infer_input_layer_names'])!=0:
                        if isinstance(model,tf.keras.models.Model):
                            model_inputs=[]
                            model_outputs=[]
                            if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in acoustic_model_json['infer_input_layer_names']:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in acoustic_model_json['infer_output_layer_name']:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model

        else:
            if acoustic_model_json['filetype']=='source':
                modulename=acoustic_model_json['modulename']
                classname=acoustic_model_json['classname']
                attribute=acoustic_model_json['attribute']
                parameters=acoustic_model_json['parameters']

                if acoustic_model_json['infer_classname']!='':
                    if acoustic_model_json['infer_classname']==acoustic_model_json['classname']:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        ins=obj(*t,**d)
                        res=list()
                        for a in (attribute,acoustic_model_json['infer_attribute']):
                            if a=='':
                                res.append(ins)
                            else:
                                func_params=a.split('(',1)
                                ins=getattr(ins,func_params[0])
                                if len(func_params)>1:
                                    t,d=parseParams(func_params[1][:-1])
                                    res.append(ins(*t,**d))
                                else:
                                    res.append(ins)
                        if isinstance(res[0],tf.keras.models.Model):
                            for r in res:
                                load_weights_keras(r,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                        return tuple(res)
                    else:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        infer_obj=dynamic_import(f'{modulename}:{acoustic_model_json["infer_classname"]}')
                        infer_t,infer_d=parseParams(acoustic_model_json['infer_parameters'])
                        model,infer_model=obj(*t,**d),infer_obj(*infer_t,**infer_d)
                        if isinstance(model,tf.keras.models.Model):
                            load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                            load_weights_keras(infer_model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                        return model,infer_model
                elif len(acoustic_model_json['infer_input_layer_names'])!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,tf.keras.models.Model):
                        load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                        model_inputs=[]
                        model_outputs=[]
                        if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in acoustic_model_json['infer_input_layer_names']:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in acoustic_model_json['infer_output_layer_name']:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                    return model,infer_model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,tf.keras.models.Model):
                        load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                    return model,model
            
            elif acoustic_model_json['filetype']=='framework_save':
                if acoustic_model_json['framework']=='tf.keras':
                    model=load_model_from_framework_save_keras(acoustic_model_json['file'],acoustic_model_json['file_ext'])
                    load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])

                    if len(acoustic_model_json['infer_input_layer_names'])!=0:
                        if isinstance(model,tf.keras.models.Model):
                            model_inputs=[]
                            model_outputs=[]
                            if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in acoustic_model_json['infer_input_layer_names']:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in acoustic_model_json['infer_output_layer_name']:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model

    elif situation=='infer':
        if acoustic_model_json['weights_file']=='':
            if acoustic_model_json['filetype']=='source':
                modulename=acoustic_model_json['modulename']
                classname=acoustic_model_json['classname']
                attribute=acoustic_model_json['attribute']
                parameters=acoustic_model_json['parameters']

                if acoustic_model_json['infer_classname']!='':
                    return return_ins(modulename,acoustic_model_json['infer_classname'],acoustic_model_json['infer_parameters'],acoustic_model_json['infer_attribute'])
                elif len(acoustic_model_json['infer_input_layer_names'])!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,tf.keras.models.Model):
                        model_inputs=[]
                        model_outputs=[]
                        if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in acoustic_model_json['infer_input_layer_names']:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in acoustic_model_json['infer_output_layer_name']:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                    return infer_model
                else:
                    return return_ins(modulename,classname,parameters,attribute)
            
            elif acoustic_model_json['filetype']=='framework_save':
                if acoustic_model_json['framework']=='tf.keras':
                    model=load_model_from_framework_save_keras(acoustic_model_json['file'],acoustic_model_json['file_ext']) # acoustic_model_json['file_ext']必须=='saved_model'

                    if len(acoustic_model_json['infer_input_layer_names'])!=0:
                        if isinstance(model,tf.keras.models.Model):
                            model_inputs=[]
                            model_outputs=[]
                            if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in acoustic_model_json['infer_input_layer_names']:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in acoustic_model_json['infer_output_layer_name']:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model

        else:
            if acoustic_model_json['filetype']=='source':
                modulename=acoustic_model_json['modulename']
                classname=acoustic_model_json['classname']
                attribute=acoustic_model_json['attribute']
                parameters=acoustic_model_json['parameters']

                if acoustic_model_json['infer_classname']!='':
                    model=return_ins(modulename,acoustic_model_json['infer_classname'],acoustic_model_json['infer_parameters'],acoustic_model_json['infer_attribute'])
                    load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                    return model
                elif len(acoustic_model_json['infer_input_layer_names'])!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                    if isinstance(model,tf.keras.models.Model):
                        model_inputs=[]
                        model_outputs=[]
                        if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in acoustic_model_json['infer_input_layer_names']:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in acoustic_model_json['infer_output_layer_name']:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                    return infer_model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])
                    return model
            
            elif acoustic_model_json['filetype']=='framework_save':
                if acoustic_model_json['framework']=='tf.keras':
                    model=load_model_from_framework_save_keras(acoustic_model_json['file'],acoustic_model_json['file_ext'])
                    load_weights_keras(model,acoustic_model_json['weights_file'],acoustic_model_json['weights_type'])

                    if len(acoustic_model_json['infer_input_layer_names'])!=0:
                        if isinstance(model,tf.keras.models.Model):
                            model_inputs=[]
                            model_outputs=[]
                            if acoustic_model_json['infer_input_layer_names'][0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in acoustic_model_json['infer_input_layer_names']:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in acoustic_model_json['infer_output_layer_name']:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model

def get_model_ins(acoustic_model,situation):
    if situation=='train':
        if acoustic_model.weights_file=='' or acoustic_model.weights_file is None:
            if acoustic_model.filetype==0:
                modulename=acoustic_model.modulename
                classname=acoustic_model.classname
                attribute=acoustic_model.attribute
                parameters=acoustic_model.parameters

                if acoustic_model.infer_classname!='':
                    if acoustic_model.infer_classname==acoustic_model.classname:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        ins=obj(*t,**d)
                        res=list()
                        for a in (attribute,acoustic_model.infer_attribute):
                            if a=='':
                                res.append(ins)
                            else:
                                func_params=a.split('(',1)
                                ins1=getattr(ins,func_params[0])
                                if len(func_params)>1:
                                    t,d=parseParams(func_params[1][:-1])
                                    res.append(ins1(*t,**d))
                                else:
                                    res.append(ins1)
                        return tuple(res)
                    else:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        infer_obj=dynamic_import(f'{modulename}:{acoustic_model.infer_classname}')
                        infer_t,infer_d=parseParams(acoustic_model.infer_parameters)
                        return obj(*t,**d),infer_obj(*infer_t,**infer_d)
                elif len(acoustic_model.infer_input_layer_names)!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        model_inputs=[]
                        model_outputs=[]
                        if infer_input_layer_names[0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in infer_input_layer_names:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in infer_output_layer_names:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    return model,model
            
            elif acoustic_model.filetype==1:
                if acoustic_model.framework==0:
                    model=load_model_from_framework_save_keras(acoustic_model.file,acoustic_model.file_ext) # file_ext有saved_model、json和config三种取值

                    if len(acoustic_model.infer_input_layer_names)!=0:
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        if isinstance(model,keras_model_type):
                            model_inputs=[]
                            model_outputs=[]
                            if infer_input_layer_names[0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in infer_input_layer_names:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in infer_output_layer_names:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model
                elif acoustic_model.framework==1:
                    model=load_model_from_framework_save_pytorch(acoustic_model.file,acoustic_model.file_ext)
                    return model,model
        else:
            if acoustic_model.filetype==0:
                modulename=acoustic_model.modulename
                classname=acoustic_model.classname
                attribute=acoustic_model.attribute
                parameters=acoustic_model.parameters

                if acoustic_model.infer_classname!='':
                    if acoustic_model.infer_classname==acoustic_model.classname:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        ins=obj(*t,**d)
                        res=list()
                        for a in (attribute,acoustic_model.infer_attribute):
                            if a=='':
                                res.append(ins)
                            else:
                                func_params=a.split('(',1)
                                ins1=getattr(ins,func_params[0])
                                if len(func_params)>1:
                                    t,d=parseParams(func_params[1][:-1])
                                    res.append(ins1(*t,**d))
                                else:
                                    res.append(ins1)
                        if isinstance(res[0],keras_model_type):
                            for r in res:
                                load_weights_keras(r,acoustic_model.weights_file,acoustic_model.weights_type)
                        elif isinstance(res[0],pytorch_model_type):
                            for r in res:
                                load_weights_pytorch(r,acoustic_model.weights_file,acoustic_model.weights_type)
                        return tuple(res)
                    else:
                        obj=dynamic_import(f'{modulename}:{classname}')
                        t,d=parseParams(parameters)
                        infer_obj=dynamic_import(f'{modulename}:{acoustic_model.infer_classname}')
                        infer_t,infer_d=parseParams(acoustic_model.infer_parameters)
                        model,infer_model=obj(*t,**d),infer_obj(*infer_t,**infer_d)
                        if isinstance(model,keras_model_type):
                            load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                            load_weights_keras(infer_model,acoustic_model.weights_file,acoustic_model.weights_type)
                        elif isinstance(model,pytorch_model_type):
                            load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)
                            load_weights_pytorch(infer_model,acoustic_model.weights_file,acoustic_model.weights_type)
                        return model,infer_model
                elif len(acoustic_model.infer_input_layer_names)!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                        model_inputs=[]
                        model_outputs=[]
                        if infer_input_layer_names[0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in infer_input_layer_names:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in infer_output_layer_names:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    elif isinstance(model,pytorch_model_type):
                        load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    return model,model
            
            elif acoustic_model.filetype==1:
                if acoustic_model.framework==0:
                    model=load_model_from_framework_save_keras(acoustic_model.file,acoustic_model.file_ext)
                    load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)

                    if len(acoustic_model.infer_input_layer_names)!=0:
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        if isinstance(model,keras_model_type):
                            model_inputs=[]
                            model_outputs=[]
                            if infer_input_layer_names[0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in infer_input_layer_names:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in infer_output_layer_names:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return model,infer_model
                    else:
                        return model,model
                elif acoustic_model.framework==1:
                    model=load_model_from_framework_save_pytorch(acoustic_model.file,acoustic_model.file_ext)
                    load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    return model,model

    elif situation=='infer':
        if acoustic_model.weights_file=='':
            if acoustic_model.filetype==0:
                modulename=acoustic_model.modulename
                classname=acoustic_model.classname
                attribute=acoustic_model.attribute
                parameters=acoustic_model.parameters

                if acoustic_model.infer_classname!='':
                    return return_ins(modulename,acoustic_model.infer_classname,acoustic_model.infer_parameters,acoustic_model.infer_attribute)
                elif len(acoustic_model.infer_input_layer_names)!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        model_inputs=[]
                        model_outputs=[]
                        if infer_input_layer_names[0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in infer_input_layer_names:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in infer_output_layer_names:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model
                else:
                    return return_ins(modulename,classname,parameters,attribute)
            
            elif acoustic_model.filetype==1:
                if acoustic_model.framework==0:
                    model=load_model_from_framework_save_keras(acoustic_model.file,acoustic_model.file_ext)

                    if len(acoustic_model.infer_input_layer_names)!=0:
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        if isinstance(model,keras_model_type):
                            model_inputs=[]
                            model_outputs=[]
                            if infer_input_layer_names[0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in infer_input_layer_names:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in infer_output_layer_names:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model
                elif acoustic_model.framework==1:
                    model=load_model_from_framework_save_pytorch(acoustic_model.file,acoustic_model.file_ext)
                    return model
        else:
            if acoustic_model.filetype==0:
                modulename=acoustic_model.modulename
                classname=acoustic_model.classname
                attribute=acoustic_model.attribute
                parameters=acoustic_model.parameters

                if acoustic_model.infer_classname!='':
                    model=return_ins(modulename,acoustic_model.infer_classname,acoustic_model.infer_parameters,acoustic_model.infer_attribute)
                    if isinstance(model,keras_model_type):
                        load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    elif isinstance(model,pytorch_model_type):
                        load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    return model
                elif len(acoustic_model.infer_input_layer_names)!=0:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                        model_inputs=[]
                        model_outputs=[]
                        if infer_input_layer_names[0]=='model.input':
                            model_inputs=model.input
                        else:
                            for iiln in infer_input_layer_names:
                                model_inputs.append(model.get_layer(iiln))
                        for ioln in infer_output_layer_names:
                            model_outputs.append(model.get_layer(ioln).output)
                        infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model
                else:
                    model=return_ins(modulename,classname,parameters,attribute)
                    if isinstance(model,keras_model_type):
                        load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    elif isinstance(model,pytorch_model_type):
                        load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)
                    return model
            
            elif acoustic_model.filetype==1:
                if acoustic_model.framework==0:
                    model=load_model_from_framework_save_keras(acoustic_model.file,acoustic_model.file_ext)
                    load_weights_keras(model,acoustic_model.weights_file,acoustic_model.weights_type)

                    if len(acoustic_model.infer_input_layer_names)!=0:
                        infer_input_layer_names=acoustic_model.infer_input_layer_names.split(',')
                        infer_output_layer_names=acoustic_model.infer_output_layer_names.split(',')
                        if isinstance(model,keras_model_type):
                            model_inputs=[]
                            model_outputs=[]
                            if infer_input_layer_names[0]=='model.input':
                                model_inputs=model.input
                            else:
                                for iiln in infer_input_layer_names:
                                    model_inputs.append(model.get_layer(iiln))
                            for ioln in infer_output_layer_names:
                                model_outputs.append(model.get_layer(ioln).output)
                            infer_model=tf.keras.models.Model(inputs=model_inputs,outputs=model_outputs)
                        return infer_model
                    else:
                        return model
                elif acoustic_model.framework==1:
                    model=load_model_from_framework_save_pytorch(acoustic_model.file,acoustic_model.file_ext)
                    load_weights_pytorch(model,acoustic_model.weights_file,acoustic_model.weights_type)

if __name__=='__main__':
    # load_logging_config()
    # acoustic_model_json_file='jsons/acoustic_models/SpeechModel251BN.json'
    # acoustic_model_json=load_from_json(acoustic_model_json_file)
    acoustic_model_json=json.loads('{"id": 1, "name": "SpeechModel251BN1Sma", "typ": 0, "filetype": 0, "content": 0, "weights_file": "", "weights_type": -1, "file": "acoustic_models.keras_backend", "modulename": "acoustic_models.keras_backend", "classname": "SpeechModel251BNSmall", "infer_classname": "SpeechModel251BNSmall", "infer_parameters": "(1600,200,1),1429", "infer_attribute": "model_base", "infer_input_layer_names": "", "infer_output_layer_names": "", "optimizer_modulename": "tensorflow.keras.optimizers", "optimizer_classname": "Adam", "optimizer_parameters": "learning_rate=0.0001, beta_1=0.9, beta_2=0.999, weight_decay=0.0, epsilon=10e-8", "optimizer_attribute": "", "loss_modulename": "acoustic_models.keras_backend", "loss_classname": "sm251bn_loss", "loss_parameters": "", "loss_attribute": "", "parameters": "(1600,200,1),1429", "attribute": "model", "file_ext": -1, "framework": -1, "structure": null, "inputs": null, "outputs": null, "param_total": null, "param_trainable": null, "param_non": null, "flops": null, "last_active": "2023-06-23 18:09:03"}')
    if acoustic_model_json['typ']==0:
        acoustic_model_json['typ']='dl'
    elif acoustic_model_json['typ']==1:
        acoustic_model_json['typ']='dnn+hmm'
    elif acoustic_model_json['typ']==2:
        acoustic_model_json['typ']='gmm+hmm'
    if acoustic_model_json['filetype']==0:
        acoustic_model_json['filetype']='source'
    elif acoustic_model_json['filetype']==1:
        acoustic_model_json['filetype']='framework_save'
    if acoustic_model_json['content']==0:
        acoustic_model_json['content']='structure'
    elif acoustic_model_json['content']==1:
        acoustic_model_json['content']='structure+weights'
    if acoustic_model_json['weights_type']==0:
        acoustic_model_json['weights_type']='keras_weights'
    elif acoustic_model_json['weights_type']==1:
        acoustic_model_json['weights_type']='keras_ckpt'
    if acoustic_model_json['file_ext']==0:
        acoustic_model_json['file_ext']='saved_model'
    elif acoustic_model_json['file_ext']==1:
        acoustic_model_json['file_ext']='json'
    elif acoustic_model_json['file_ext']==2:
        acoustic_model_json['file_ext']='config'
    if acoustic_model_json['framework']==0:
        acoustic_model_json['framework']='tf.keras'
    model=get_model_ins_from_json(acoustic_model_json,'train')
    # parseParams('(1600,200,1),1429')